# -*- coding: utf-8 -*-
# owner: shenyi
# src/cli/cli.py

from urllib import request
from src.constants import (
    PROVIDER_CREDENTIAL_META,
    SUPPORTED_PROVIDERS,
    DEFAULT_PROVIDER_ENV_KEY,
)
from src.utils.env import read_env_file, write_env_file
from src.utils.mask import mask_secret
from src.utils.decorators import async_command
import click
from pathlib import Path
from src.core import setup_app, ApplicationContext
import importlib.metadata
from src import __version__
import os
from src.models.instance import (
    CreateInstanceRequest,
    DeleteInstanceRequest,
    QueryInstanceRequest,
)


@click.group()
@click.option(
    "--env-file",
    type=click.Path(exists=True, dir_okay=False, path_type=Path),
    default=None,
    help="指定 .env 文件路径（默认自动查找）",
)
@click.help_option("-h", "--help")  # ← 显式启用 -h
@click.pass_context
def cli(ctx, env_file: Path | None):
    """CloudKit CLI 工具 —— 多云资源管理命令行"""
    # ✅ 在 CLI 启动时初始化全局应用上下文
    app_ctx = setup_app(env_path=env_file)

    # 将上下文存入 Click 的 ctx.obj
    ctx.ensure_object(dict)
    ctx.obj["app"] = app_ctx  # 类型安全，结构清晰


@cli.command()
@click.option(
    "--provider",
    "-p",
    type=click.Choice(SUPPORTED_PROVIDERS),
    required=False,
    help="云厂商（可选，未设置时使用默认）",
)
@click.pass_context
@async_command
async def list_instances(ctx: click.Context, provider: str):
    """列出指定云厂商的所有实例"""
    from src.services.instance import InstanceService

    app: ApplicationContext = ctx.obj["app"]
    logger = app.logger

    logger.info(f"Listing instances for provider: {provider}")

    service = InstanceService(provider)
    request = QueryInstanceRequest()
    response = await service.list_instances(request=request)

    if not response.instances:
        click.echo(click.style("No instances found.", fg="yellow"))
        return

    for inst in response.instances:
        click.echo(f"• {inst}")


@cli.command()
@click.option(
    "--provider",
    "-p",
    type=click.Choice(SUPPORTED_PROVIDERS),
    required=False,
    help="云厂商（可选，未设置时使用默认）",
)
@click.option("--instance-type", "-t", required=True, help="实例类型，如: ecs.g6.large")
@click.option("--image-id", "-i", required=True, help="镜像ID")
@click.option("--host-name", "-n", required=True, help="主机名")
@click.option("--zone-id", "-z", help="可用区ID（可选）")
@click.option("--launch-template-id", help="启动模板ID")
@click.option("--launch-template-version", default="1", help="启动模板版本")
@click.pass_context
@async_command
async def create_instance(
    ctx: click.Context,
    provider: str,
    instance_type: str,
    image_id: str,
    host_name: str,
    launch_template_id: str,
    launch_template_version: str,
):
    """创建云服务器实例"""
    from src.services.instance import InstanceService

    app: ApplicationContext = ctx.obj["app"]
    logger = app.logger

    logger.info(f"Creating instance for provider: {provider}")

    # 构造请求对象
    request = CreateInstanceRequest(
        host_name=host_name,
        instance_type=instance_type,
        image_id=image_id,
        launch_template_id=launch_template_id or "",
        launch_template_version=launch_template_version,
        data_disk=[],
    )

    # 创建服务实例
    service = InstanceService(provider)

    try:
        response = await service.create_instance(request)
        if response.status_code == 200:
            click.echo(click.style(f"✅ 实例创建成功!", fg="green"))
            if response.instance_ids:
                click.echo(f"实例ID: {', '.join(response.instance_ids)}")
        else:
            click.echo(click.style(f"❌ 实例创建失败: {response.message}", fg="red"))
    except Exception as e:
        click.echo(click.style(f"❌ 实例创建异常: {str(e)}", fg="red"))


@cli.command()
@click.option(
    "--provider",
    "-p",
    type=click.Choice(SUPPORTED_PROVIDERS),
    required=False,
    help="云厂商（可选，未设置时使用默认）",
)
@click.option("--instance-id", "-i", required=True, help="实例ID")
@click.option("--zone-id", "-z", help="可用区ID（可选）")
@click.confirmation_option(prompt="确定要删除该实例吗?")
@click.pass_context
@async_command
async def delete_instance(
    ctx: click.Context, provider: str, instance_id: str, zone_id: str
):
    """删除云服务器实例"""
    from src.services.instance import InstanceService

    app: ApplicationContext = ctx.obj["app"]
    logger = app.logger

    logger.info(f"Deleting instance {instance_id} for provider: {provider}")

    # 构造请求对象
    request = DeleteInstanceRequest(instance_id=instance_id, zone_id=zone_id)

    # 创建服务实例
    service = InstanceService(provider)

    try:
        response = await service.delete_instance(request)
        if response.status_code == 200:
            click.echo(click.style(f"✅ 实例删除成功!", fg="green"))
        elif response.status_code == 404:
            click.echo(click.style(f"❌ 实例未找到: {response.message}", fg="yellow"))
        else:
            click.echo(click.style(f"❌ 实例删除失败: {response.message}", fg="red"))
    except Exception as e:
        click.echo(click.style(f"❌ 实例删除异常: {str(e)}", fg="red"))


# =============================================================================
# config 命令组
# =============================================================================
@click.group(
    help="配置云厂商凭据和默认设置",
    invoke_without_command=True,  # ← 关键：没有子命令时也执行本组函数
)
@click.pass_context
def config_group(ctx):
    """
    配置管理命令组。
    执行 `cloudkit config` 默认进入交互式配置向导。
    """
    # 如果没有子命令，就执行 wizard
    if ctx.invoked_subcommand is None:
        ctx.invoke(config_wizard)


@config_group.command(name="wizard", help="交互式配置云厂商凭据")
@click.pass_context
def config_wizard(ctx: click.Context):
    """启动交互式配置向导"""
    app: ApplicationContext = ctx.obj["app"]
    config = app.config

    click.echo("☁️  CloudKit 配置向导")
    click.echo("=" * 40)

    provider = click.prompt(
        "请选择云服务提供商",
        type=click.Choice(SUPPORTED_PROVIDERS),
        show_choices=True,
    )

    new_vars = {}
    meta = PROVIDER_CREDENTIAL_META[provider]

    if provider == "google":
        cred_file = click.prompt("Google 应用凭据 JSON 文件路径")
        cred_file = os.path.abspath(os.path.expanduser(cred_file))
        if not os.path.isfile(cred_file):
            click.echo(click.style("⚠️  警告：文件不存在", fg="yellow"))
        new_vars[meta["credentials_file"]] = cred_file
        if "project_id" in meta:
            new_vars[meta["project_id"]] = click.prompt("Project ID")
    else:
        new_vars[meta["key"]] = click.prompt(meta["display_name"])
        new_vars[meta["secret"]] = click.prompt("Secret", hide_input=True)
        if "region" in meta:
            default_region = {
                "aliyun": "cn-hangzhou",
                "aws": "us-east-1",
                "tencent": "ap-guangzhou",
            }.get(provider, "")
            new_vars[meta["region"]] = click.prompt("Region", default=default_region)
        if "project_id" in meta:
            new_vars[meta["project_id"]] = click.prompt("Project ID")

    # 读取并更新 .env 文件
    env_path = config.env_path
    data = read_env_file(env_path)
    data.update(new_vars)
    write_env_file(env_path, data)

    click.echo(click.style(f"\n✅ 凭据已保存到 {env_path}", fg="green"))


@config_group.command(name="list", help="列出当前已配置的云服务提供商")
@click.pass_context
def config_list(ctx: click.Context):
    """列出所有已配置的云厂商状态"""
    app: ApplicationContext = ctx.obj["app"]
    config = app.config

    click.echo("🔧 已配置的云服务提供商：")
    click.echo("-" * 40)

    for provider in SUPPORTED_PROVIDERS:
        meta = PROVIDER_CREDENTIAL_META[provider]
        key = meta.get("key") or meta.get("credentials_file")
        value = config.get(key)
        status = "✅" if value else "❌"
        display = (
            mask_secret(value, meta["mask_len"])
            if value
            else f"(未设置 {meta['display_name']})"
        )
        click.echo(f"  {status} {provider:<10} ({display})")

    # 显示默认厂商
    current_default = config.get(DEFAULT_PROVIDER_ENV_KEY)
    if current_default:
        click.echo(f"\n📌 当前默认云厂商: {current_default}")
    else:
        click.echo("\n📌 默认云厂商: 未设置")

    click.echo(f"\n📄 配置文件路径: {config.env_path}")


@config_group.command(name="default-provider", help="设置或查看默认云厂商")
@click.argument("provider", type=click.Choice(SUPPORTED_PROVIDERS), required=False)
@click.pass_context
def config_default_provider(ctx: click.Context, provider: str):
    """
    设置或查看默认云厂商。

    示例：
        cloudkit config default-provider      # 查看当前默认
        cloudkit config default-provider aws  # 设置为 aws
    """
    app: ApplicationContext = ctx.obj["app"]
    config_obj = app.config
    env_path = config_obj.env_path

    if provider is None:
        current = config_obj.get(DEFAULT_PROVIDER_ENV_KEY)
        if current:
            click.echo(f"当前默认云厂商: {current}")
        else:
            click.echo("尚未设置默认云厂商。")
        return

    # 更新 .env 文件
    data = read_env_file(env_path)
    data[DEFAULT_PROVIDER_ENV_KEY] = provider
    write_env_file(env_path, data)

    click.echo(click.style(f"✅ 默认云厂商已设置为: {provider}", fg="green"))
    click.echo(f"配置已保存至 {env_path}")


# 将 config_group 挂载为 cli 的子命令
cli.add_command(config_group)


@cli.command()
def version():
    """显示 CloudKit CLI 的版本信息"""
    try:
        # 尝试从安装的包中获取版本（适用于 pip install 后）
        pkg_version = importlib.metadata.version("cloudkit")
    except importlib.metadata.PackageNotFoundError:
        # 未安装时回退到源码中的 __version__
        pkg_version = __version__

    click.echo(f"CloudKit CLI version: {pkg_version}")


# =============================================================================
# 主入口
# =============================================================================

if __name__ == "__main__":
    cli()
